//
// Created by admin on 2023/1/30.
//
#include <jni.h>
#include "../conn/serial_port.h"
#include "../utils/log.h"

using namespace utils;
using namespace conn;

#define JNI_FUNC(FUNC_NAME)     Java_com_hontech_kaltaapp_serial_TTYSerialPort_00024Companion_##FUNC_NAME

extern "C"
JNIEXPORT jlong JNICALL
JNI_FUNC(open)(JNIEnv *env, jobject thiz, jstring name, jint baud_rate) {
    jlong ret = -1;

    const char *c_name = env->GetStringUTFChars(name, nullptr);

    try {
        auto port = new SerialPort(c_name, baud_rate);
        ret = reinterpret_cast<jlong>(port);
        log_d("open serial port %s succ", c_name);
    } catch (...) {
        log_e("open serial port fail");
        ret = -1;
    }

    env->ReleaseStringUTFChars(name, c_name);

    return ret;
}

extern "C"
JNIEXPORT void JNICALL
JNI_FUNC(close)(JNIEnv *env, jobject thiz, jlong ref) {
    auto port = reinterpret_cast<SerialPort *>(ref);
    delete port;
}


extern "C"
JNIEXPORT jint JNICALL
JNI_FUNC(sync)(JNIEnv *env, jobject thiz, jlong ref) {

    try {
        auto port = reinterpret_cast<SerialPort *>(ref);
        return port->sync();
    } catch (...) {
        log_e("sync fail or closed");
        return -1;
    }
}


extern "C"
JNIEXPORT jint JNICALL
JNI_FUNC(readBytes)(JNIEnv *env, jobject thiz, jlong ref, jbyteArray buf) {

    auto c_buf = env->GetByteArrayElements(buf, nullptr);
    auto c_size = env->GetArrayLength(buf);
    auto bytes = reinterpret_cast<uint8_t *>(c_buf);
    auto port = reinterpret_cast<SerialPort *>(ref);

    try {
        port->read_bytes(bytes, c_size);
    } catch (...) {
        log_e("read fail or closed");
        return -1;
    }

    env->ReleaseByteArrayElements(buf, c_buf, 0);

    return c_size;
}


extern "C"
JNIEXPORT void JNICALL
JNI_FUNC(write)(JNIEnv *env, jobject thiz, jlong ref, jbyteArray buf) {

    auto c_buf = env->GetByteArrayElements(buf, nullptr);
    auto c_size = env->GetArrayLength(buf);
    auto port = reinterpret_cast<SerialPort *>(ref);

    port->write(c_buf, c_size);

    env->ReleaseByteArrayElements(buf, c_buf, JNI_ABORT);
}




extern "C"
JNIEXPORT void JNICALL
JNI_FUNC(notifyClose)(JNIEnv *env, jobject thiz, jlong ref) {
    reinterpret_cast<SerialPort *>(ref)->notify_read_exit();
}
